package com.panfeng.xcloud.boss.provider.assets.aop;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.Set;

/**
 *
 * 在特定方法执行前刷新一下缓存
 *
 * @author xiaobo
 * @version 1.0
 * @since 2018-12-28
 */
@Component
@Aspect
@Slf4j
public class RefreshCacheAspect {

	@Resource
	private RedisTemplate<String, String> redisTemplate;

	@Pointcut("@annotation(com.panfeng.xcloud.boss.provider.assets.aop.RefreshCache)")
	public void refreshCacheAnnotation() {
	}

	@Before("refreshCacheAnnotation()")
	public void doBefore(final JoinPoint joinPoint) {
		String methodName = joinPoint.getSignature().getName();
		Object target = joinPoint.getTarget();
		Method method = getMethodByClassAndName(target.getClass(), methodName);
		assert method != null;
		RefreshCache refreshCache = (RefreshCache) getAnnotationByMethod(method, RefreshCache.class);
		if (null != refreshCache) {
			log.info(">>> 开始批量删除缓存,方法签名：{} <<< ",methodName);
			String[] refreshKeysPrefix = refreshCache.refreshKeysPrefix();
			if(null != refreshKeysPrefix && refreshKeysPrefix.length > 0){
				for(String refreshKeyPrefix : refreshKeysPrefix){
					log.info(">>> 开始批量缓存前缀为：{}的缓存 --> 方法签名：{} <<< ",refreshKeyPrefix ,methodName);
					Set<String> keys = redisTemplate.keys(refreshKeyPrefix + "*");
					if(null != keys && !keys.isEmpty()){
						Long resultCount = redisTemplate.delete(keys);
						log.info(">>> 开始批量缓存前缀为：{} 且key列表为：{} 的缓存 --> 方法签名：{} ,删除条数：{}  <<< ",refreshKeyPrefix ,keys,methodName,resultCount);
					}
				}
			}
		}
	}

	/**
	 * 根据目标方法和注解类型  得到该目标方法的指定注解
	 */
	private Annotation getAnnotationByMethod(Method method, Class annoClass) {
		Annotation[] all = method.getAnnotations();
		for (Annotation annotation : all) {
			if (annotation.annotationType() == annoClass) {
				return annotation;
			}
		}
		return null;
	}

	/**
	 * 根据类和方法名得到方法
	 */
	private Method getMethodByClassAndName(Class c, String methodName) {
		Method[] methods = c.getDeclaredMethods();
		for (Method method : methods) {
			if (method.getName().equals(methodName)) {
				return method;
			}
		}
		return null;
	}
}
